#include <cstdio>
#include <cstring>
#include "AugmentedObjects.h"
#include "SimpleVectorMatrix.h"
#include "glm.h"
#include "gltb.h"
#include "FaceModel.h"
#include <GL/glut.h>
#include <GL/gl.h>

std::vector<DrawAugmentedObjectFunc> objectFunctions;
std::vector<std::string*> objectNames;
std::vector<bool> activeObjects;

std::vector<GLMmodel*> loadedObjects;


GLMmodel *hat, *eyes, *glasses, *rabbitEars;

void registerObject(const char* name, DrawAugmentedObjectFunc drawingFunc)
{
	std::string* nameString = new std::string(name);
	objectNames.push_back(nameString);
	objectFunctions.push_back(drawingFunc);
}

void loadOBJ(GLMmodel** object, char* file)
{
	printf("Loading %s...\n", file);
	*object = glmReadOBJ(file);
	glmUnitize(*object);
    glmFacetNormals(*object);
    glmVertexNormals(*object, 0);
	loadedObjects.push_back(*object);
	printf("Done!\n", file);
}

void initModels()
{
	// Load the OBJ models form the files
	loadOBJ(&hat, "hat.obj");
	loadOBJ(&eyes, "cartoonEyes.obj");
	loadOBJ(&glasses, "spectaclesPink.obj");
	loadOBJ(&rabbitEars, "rabbitEars.obj");

	// Register each object's function
	registerObject("Red Nose", showRedNose);
	registerObject("Hat", showHat);
	registerObject("Cartoon Eyes", showCartoonEyes);
	registerObject("Glasses", showGlasses);
	registerObject("Rabbit Ears", showRabbitEars);
	
	// Init the active objects array
	activeObjects.resize(objectFunctions.size(), false);
}

void freeModels()
{
	for (int i=0; i<loadedObjects.size(); ++i)
		glmDelete(loadedObjects[i]);

	for (int i=0; i<objectNames.size(); ++i)
		delete[] objectNames[i];
}

void displayActiveModels(float *pose_matrix)
{
	float transposed_pose_matrix[16];
	memcpy(transposed_pose_matrix, pose_matrix, 16*sizeof(float));

	transposeMatrix16(transposed_pose_matrix);
	
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
	glLoadMatrixf(transposed_pose_matrix);
	glScalef(0.04f, 0.04f, 0.04f);
	
	for (int i=0; i<activeObjects.size(); ++i)
	{
		if (activeObjects[i])
		{
			glPushMatrix();
			objectFunctions[i]();
			glPopMatrix();
		}
	}	
}


// *** Object Functions *** //

void showRedNose()
{
	GLfloat red[4] = {0.6f, 0.0f, 0.0f, 1.0f};
	GLfloat white[4] = {0.01f, 0.01f, 0.01f, 1.0f};

	glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, red);
	glMaterialfv(GL_FRONT, GL_SPECULAR, white);
	glMateriali(GL_FRONT, GL_SHININESS, 1);

	glTranslatef(0.0f, -1.8f, 0.2f);
	
	glutSolidSphere(0.5, 50, 50);
}

void showHat()
{
	glScalef(4.9f, 4.9f, 4.9f);
	glRotatef(180, 0, 1, 0);
	glRotatef(28, 1, 0, 0);
	glTranslatef(0.0f, 0.4f, -0.8f);

	GLuint model_list = glmList(hat, GLM_FLAT | GLM_MATERIAL);

	glCallList(model_list);

}

void showCartoonEyes()
{
	glScalef(1.3f, 1.3f, 1.3f);
	glRotatef(180, 0, 1, 0);
	glRotatef(15, 1, 0, 0);
	glTranslatef(0.0f, -0.9f, -0.3f);

	GLuint model_list = glmList(eyes, GLM_SMOOTH | GLM_MATERIAL);

	glCallList(model_list);

}

void showGlasses()
{
	faceModel.applyTransformMatrix(EYES_LINE);

	glRotatef(180, 0, 1, 0);
	glRotatef(20, 1, 0, 0);
	
	//glTranslatef(0.0f, -1.1f, -0.2f);

	glScalef(25, 25, 25);

	GLuint model_list = glmList(glasses, GLM_SMOOTH | GLM_MATERIAL);

	glCallList(model_list);
}

void showRabbitEars()
{
	glRotatef(90, 0, 1, 0);
	//glRotatef(20, 1, 0, 0);
	glTranslatef(-1.5f, 4.5f, 0.0f);

	glScalef(15, 15, 15);

	GLuint model_list = glmList(rabbitEars, GLM_SMOOTH | GLM_MATERIAL);

	glCallList(model_list);
}
